﻿using Microsoft.Practices.EnterpriseLibrary.Logging;
using RockBus.Logging.Interfaces;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Transactions;

namespace RockBus.Logging.EntLib
{
    public class EntLibLogger : ILogger
    {
        public void Log(MethodBase currentMethod, MessageData messageData)
        {
            this.Log(currentMethod, messageData.LogLevel, MessageData.Format, new object[] {
                        messageData.MessageEvent.ToString(),
                        messageData.ReceiveAddress,
                        messageData.Action,
                        messageData.CorrelationId.ToString(),
                        messageData.Text,
                        messageData.DestinationAddress});
        }

        public void Log(MethodBase currentMethod, LogData logData)
        {
            TraceEventType tet = TraceEventType.Error;
            switch (logData.LogLevel)
            {
                case LogLevelEnum.Error:
                    tet = TraceEventType.Error;
                    break;

                case LogLevelEnum.Warning:
                    tet = TraceEventType.Warning;
                    break;

                case LogLevelEnum.Info:
                    tet = TraceEventType.Information;
                    break;

                case LogLevelEnum.Debug:
                    tet = TraceEventType.Verbose;
                    break;

                case LogLevelEnum.Verbose:
                    tet = TraceEventType.Verbose;
                    break;

                default:
                    break;
            }

            Logger.Write(
                logData.Text,
                "LogMessage",
                0,
                10000,
                tet,
                string.Empty);
        }

        public void Log(MethodBase currentMethod, LogLevelEnum logLevel, string text, params object[] args)
        {
            text = string.Format("{0}.{1}: {2}", currentMethod.DeclaringType.Name, currentMethod.Name, text);
            if ((null != args) && (args.Length > 0))
            {
                text = string.Format(text, args);
            }

            TraceEventType tet = TraceEventType.Error;
            switch (logLevel)
            {
                case LogLevelEnum.Error:
                    tet = TraceEventType.Error;
                    break;

                case LogLevelEnum.Warning:
                    tet = TraceEventType.Warning;
                    break;

                case LogLevelEnum.Info:
                    tet = TraceEventType.Information;
                    break;

                case LogLevelEnum.Debug:
                    tet = TraceEventType.Verbose;
                    break;

                case LogLevelEnum.Verbose:
                    tet = TraceEventType.Verbose;
                    break;

                default:
                    break;
            }

            Logger.Write(
                text,
                "LogMessage",
                0,
                10000,
                tet,
                string.Empty);
        }

        private void PopulateDictionary(MessageData messageData, IDictionary<string, object> dictionary)
        {
            dictionary.Add("CorrelationId", messageData.CorrelationId);
            dictionary.Add("ReceiveAddress", messageData.ReceiveAddress);
            dictionary.Add("MessageAction", messageData.Action);
            dictionary.Add("DestinationAddress", messageData.DestinationAddress);
        }

        public void Log(MethodBase currentMethod, Exception exc)
        {
            this.LogError(currentMethod, "{0}", exc);
        }

        public void LogError(MethodBase currentMethod, string text, params object[] args)
        {
            this.Log(currentMethod, LogLevelEnum.Error, text, args);
        }

        public void LogWarning(MethodBase currentMethod, string text, params object[] args)
        {
            this.Log(currentMethod, LogLevelEnum.Warning, text, args);
        }

        public void LogInfo(MethodBase currentMethod, string text, params object[] args)
        {
            this.Log(currentMethod, LogLevelEnum.Info, text, args);
        }

        public void LogDebug(MethodBase currentMethod, string text, params object[] args)
        {
            this.Log(currentMethod, LogLevelEnum.Debug, text, args);
        }

        public void LogVerbose(MethodBase currentMethod, string text, params object[] args)
        {
            this.Log(currentMethod, LogLevelEnum.Verbose, text, args);
        }

        public void Log(MethodBase currentMethod, LogLevelEnum logLevel, Transaction transaction)
        {
            if (null == transaction)
            {
                this.Log(currentMethod, logLevel, "Transaction: None");
            }
            else
            {
                this.Log(currentMethod, logLevel, "{0}, {1}, {2}, {3}",
                    transaction.TransactionInformation.CreationTime,
                    transaction.TransactionInformation.LocalIdentifier,
                    transaction.TransactionInformation.DistributedIdentifier,
                    transaction.TransactionInformation.Status);
            }
        }
    }
}